<template>
    <div class="title" v-if="title">
        <h4 v-if="title">{{ title }}</h4>
        <div style="padding: 0 1em;">
            <slot name="edit"></slot>
        </div>
    </div>
    <div class="detail">
        <slot name="top"></slot>
        <template v-for="label, prop in labels" :key="prop">
            <Cell v-if="label && (!label.show || label.show({ data, type: 'detail', isPhone: true }))" :id="label.prop"
                :border="instance.border" :title="label.label" value-class="detail_cell"
                :title-style="'max-width:' + label.label_width">
                <component v-if="label.type === 'customize'" :is="renderFormatter(toValue(data), label)"></component>
                <component v-else :is="detailRender.render(toValue(data), label)"></component>
            </Cell>
        </template>
        <slot></slot>
    </div>
</template>

<script setup lang="ts" generic="T extends Record<string, any>">
import type { interCustomize, interFormBase } from "@b/model/base/type";
import { Form } from "@b/model/base/form";
import { computed, h, isVNode, toValue } from "vue";
import { Cell } from "vant";
import { DetailRender } from "./render_item";

interface prop {
    instance: Form<T>
    label_prop?: string;
    title?: string
}
const { instance, label_prop = "labels" } = defineProps<prop>()
const data = computed(() => instance.data)
//@ts-ignore
const l = instance[label_prop] as { [key in keyof T & string]?: interForm<T, key> }
if (!l) throw new Error('bDetail 组件需要 labels 属性')
const labels = computed(() => Object.values(l).sort((a, b) => (a.sortBy || Infinity) - (b.sortBy || Infinity)))
const spance = computed(() => instance.spance / 2 + 'px')
const detailRender = new DetailRender<T, keyof T & string>()

const renderFormatter = (
    data: T,
    item: interFormBase<T, keyof T & string> & interCustomize<T, keyof T & string>
) => {
    if (!item.formatter) return h("div");
    const prop = item.prop as keyof T & string;
    const v = item.formatter({ data, prop, value: data[prop] })
    if (isVNode(v)) {
        return v;
    } else {
        return h("div", {}, v || item.default);
    }
}
</script>

<style scoped>
.van-cell {
    padding-top: v-bind(spance);
    padding-bottom: v-bind(spance);
}

.detail {
    background-color: var(--van-background);
}

.detail :deep(.detail_cell) {
    flex-grow: 2;
}

.title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 0;
}
</style>